package com.sc.nft.controller;

import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.sc.nft.annotation.UserLogin;
import com.sc.nft.controller.request.*;
import com.sc.nft.dao.StaticDataDao;
import com.sc.nft.dto.MallOrderRefundDTO;
import com.sc.nft.entity.RefundRecordVO;
import com.sc.nft.entity.vo.DeliveryNameVO;
import com.sc.nft.entity.vo.mall.RefundDetailsVO;
import com.sc.nft.entity.vo.mall.RefundInfoVO;
import com.sc.nft.entity.vo.mall.RefundValuationVO;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.exception.GlobalException;
import com.sc.nft.pool.UserPool;
import com.sc.nft.service.MallOrderRefundService;
import com.sc.nft.service.MallOrderService;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.sup.PageRequest;
import com.sc.nft.sup.PageResult;
import com.sc.nft.sup.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.http.MediaType;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.Valid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/ipMall/refund")
@Api(tags = "IP商城订单售后")
public class IPMallOrderRefundController {

    private final MallOrderService mallOrderService;
    private final MallOrderRefundService mallOrderRefundService;
    private final Redisson redisson;
    private final StaticDataDao staticDataDao;

    @ApiOperation(value = "售后-申请售后(获取原因和类型)", notes = "售后-申请售后(获取原因和类型)", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getRefundInfo", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<RefundInfoVO> getRefundReason(@Valid @RequestBody RefundInfoRequest request) throws GlobalException {
        return Result.success(mallOrderService.getRefundReason(request.getId(), request.getOrderProductId()));
    }

    @ApiOperation(value = "售后-申请售后计价", notes = "售后-申请售后计价", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/getRefundValuation", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<RefundValuationVO> getRefundValuation(@Valid @RequestBody RefundValuationRequest request) throws GlobalException {
        return Result.success(mallOrderService.getRefundValuation(request.getId(), request.getOrderProductId(), request.getCount()));
    }

    @ApiOperation(value = "售后-提交申请", notes = "售后-提交申请", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/applyRefund", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<Long> applyRefund(@Valid @RequestBody ConfirmRefundRequest request) throws GlobalException {
        // 提交售后
        RLock lock = redisson.getLock(RedisKeyEnum.AFTER_THE_ORDER.getKey() + request.getId());
        Long id = null;
        try {
            boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS);
            if (res) {
                id = mallOrderService.applyRefund(request.getId(), request.getOrderProductId(), request.getCount(), request.getRefundReason(), request.getRefundType(), request.getImgUrl(),request.getDescription(),request.getContactNumber());
            }else{
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("已提交售后，请稍后再试");
        } finally {
            lock.unlock();
        }
        return Result.success(id);
    }

    @ApiOperation(value = "IP商城售后列表", notes = "IP商城售后列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/pageMallOrderRefund", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public PageResult<MallOrderRefundDTO> pageMallOrder(@RequestBody PageRequest request) throws GlobalException {
        return PageResult.success(mallOrderRefundService.getRefundListByUserId(UserPool.getUser().getId(), request.getPageNo(), request.getPageSize()));
    }

    @ApiOperation(value = "新售后-取消申请", notes = "新售后-取消申请", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/newCancelApplyRefund", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result cancelApplyRefund(@Valid @RequestBody NewRefundCancelRequest request) throws GlobalException {
        // 取消售后
        RLock lock = redisson.getLock(RedisKeyEnum.AFTER_THE_ORDER.getKey() + request.getId());
        try {
            boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS);
            if (res) {
                mallOrderRefundService.cancelAfterSale(request.getId());
            }else {
                return Result.fail(ErrorCode.LATER_TRY);
            }
        } catch (InterruptedException e) {
            return Result.fail("网络异常，请稍后再试");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }

    @ApiOperation(value = "新售后详情", notes = "售后-新售后详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/newRefundDetails", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<MallOrderRefundDTO> newRefundDetails(@Valid @RequestBody NewRefundDetailsRequest request) throws GlobalException {
        return PageResult.success(mallOrderRefundService.getDetailsById(request.getId()));
    }

    @ApiOperation(value = "编辑退货物流", notes = "编辑退货物流", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/editReturnLogistics", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result editReturnLogistics(@Valid @RequestBody UserReturnRequest request) throws GlobalException {
        // 编辑退货物流
        RLock lock = redisson.getLock(RedisKeyEnum.AFTER_THE_ORDER.getKey() + request.getId());
        try {
            boolean res = lock.tryLock(3, 10, TimeUnit.SECONDS);
            if (res) {
                mallOrderRefundService.userReturn(request.getId(), request.getUserDeliveryNo(), request.getUserDeliveryName());
            }
        } catch (InterruptedException e) {
            return Result.fail("网络异常，请稍后再试");
        } finally {
            lock.unlock();
        }
        return Result.success();
    }

    @ApiOperation(value = "售后-详情", notes = "售后-详情", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/refundDetails", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @Deprecated
    public Result<RefundDetailsVO> refundDetails(@Valid @RequestBody RefundDetailsRequest request) throws GlobalException {
        return PageResult.success(mallOrderService.refundDetails(request.getId(), request.getOrderProductId()));
    }

    @ApiOperation(value = "售后-取消申请", notes = "售后-取消申请", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/cancelApplyRefund", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    @Deprecated
    public Result cancelApplyRefund(@Valid @RequestBody RefundDetailsRequest request) throws GlobalException {
        mallOrderService.cancelApplyRefund(request.getId(), request.getOrderProductId());
        return PageResult.success();
    }


    @ApiOperation(value = "售后-记录", notes = "售后-记录", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/refundRecord", produces = MediaType.APPLICATION_JSON_VALUE)
    @UserLogin
    public Result<List<RefundRecordVO>> refundRecord(@Valid @RequestBody IdRequest request) throws GlobalException {
        return PageResult.success(mallOrderService.refundRecord(request.getId()));
    }

    @ApiOperation(value = "快递公司列表", notes = "营销和兑换订单列表", httpMethod = "POST", produces = MediaType.APPLICATION_JSON_VALUE)
    @PostMapping(value = "/deliveryNameList", produces = MediaType.APPLICATION_JSON_VALUE)
    public Result deliveryNameList() {
        String deliveryNameList = staticDataDao.getByType("delivery_type_name_list").getValue();
        Map<String,String> finalDeliveryNameMap = new HashMap<>();
        if (!StringUtils.isEmpty(deliveryNameList)){
            finalDeliveryNameMap = JSON.parseObject(deliveryNameList,Map.class);
        }
        List<String> nameList = finalDeliveryNameMap.values().stream().distinct().collect(Collectors.toList());
        List<DeliveryNameVO> retList = nameList.stream().map(e -> {
            DeliveryNameVO deliveryNameVO = new DeliveryNameVO();
            deliveryNameVO.setDeliveryName(e);
            return deliveryNameVO;
        }).collect(Collectors.toList());
        return Result.success(retList);
    }
}
